package com.pig4cloud.pigx.strategy.websocket.app.subscribe;


import com.pig4cloud.pigx.strategy.websocket.app.dto.WebSocketMessageDTO;
import com.pig4cloud.pigx.strategy.websocket.app.vo.AbstractTopicVO;
import jodd.util.collection.MapEntry;
import org.springframework.web.socket.WebSocketSession;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 */
public abstract class RequestDataAbstractTopic {

    public Map<WebSocketSession, AbstractTopicVO> subList = new ConcurrentHashMap<>();

    /**
     * 将会话添加到订阅列表
     *
     * @param session  会话
     * @param newParam 新参数
     * @since 2022/9/25 17:34
     */
    protected void add(WebSocketSession session, AbstractTopicVO newParam) {
        // 用户没有订阅过，直接加入订阅列表
        if (!this.subList.containsKey(session)) {
            this.subList.put(session, newParam);
            // 立即推送一次消息
            push(new MapEntry<>(session, newParam));
            return;
        }

        // 旧参数
        AbstractTopicVO oldParam = this.subList.get(session);

        // 比较新旧参数，如果不同，直接替换并结束
        if (!newParam.getData().toString().equals(oldParam.getData().toString())) {
            this.subList.put(session, newParam);
            // 立即推送一次消息
            push(new MapEntry<>(session, newParam));
        }
    }

    /**
     * 将会话移出订阅列表
     *
     * @param session 会话
     * @since 2022/9/25 17:35
     */
    protected void remove(WebSocketSession session) {
        this.subList.remove(session);
    }

    /**
     * 订阅
     *
     * @param session 会话
     * @param params  参数
     * @since 2022/9/25 17:34
     */
    public AbstractTopicVO sub(WebSocketSession session, WebSocketMessageDTO params) {
        // 转换参数为vo
        AbstractTopicVO vo = new AbstractTopicVO();
        vo.setData(params);

        // 将会话添加到订阅列表
        add(session, vo);
        return vo;
    }

    /**
     * 取消订阅
     *
     * @param session 会话
     * @since 2022/9/25 17:42
     */
    public void unSub(WebSocketSession session) {
        // 将会话移出订阅列表
        remove(session);
    }

    /**
     * 标识正在推送，并且判断是否可以继续推送
     *
     * @param vo 参数
     * @return {@link boolean} true 可以推送， false 不能推送
     * @since 2022/9/28 19:29
     */
    protected boolean startRun(AbstractTopicVO vo) {
        // 正在处理推送
        if (vo.getIsRunning()) {
            return false;
        }

        vo.setIsRunning(true);
        return true;
    }

    /**
     * 标识已结束推送
     *
     * @param vo 参数
     * @since 2022/9/28 19:29
     */
    protected void endRun(AbstractTopicVO vo) {
        vo.setIsRunning(false);
    }

    /**
     * 推送一次消息
     *
     * @param entry 参数
     * @since 2022/12/11 14:31
     */
    protected abstract void push(Map.Entry<WebSocketSession, AbstractTopicVO> entry);
}
